package com.qs.javame.thread.interrupt;

import java.util.concurrent.TimeUnit;

/**
 * 线程中断（如何优雅的结束线程？）
 *  1、通过自定义中断标志位控制线程中断，在线程中断后，完成资源释放等后续处理，让执行中的线程优雅的结束；
 *  2、通过Thread类提供的interrupt()方法，中断某个线程，可以通过thread.isInterrupted()方法返回true或false表示线程是否已经中断；
 */
public class TestInterrupt {

    public static void main(String[] args) throws InterruptedException {

        //testInterrupt();

        testInterrupt2();
    }


    /**
     * 测试：自定义中断位，控制所有使用该线程任务的线程都发生中断
     */
    public static void testInterrupt() throws InterruptedException {
        Student student = new Student();

        //新建并运行一个线程
        Thread thread = new Thread(student, "zhangsan");
        thread.start();
        Thread thread2 = new Thread(student, "lisi");
        thread2.start();

        //主线程在睡眠5s后，中断执行的线程
        TimeUnit.SECONDS.sleep(5);
        student.interrupt();
    }


    /**
     * 测试：使用Thread类中定义的中断标志位，控制线程中断。
     * 注意细节：
     *  1、thread.isInterrupted()返回true表示线程已经中断；
     *  2、如果方法出现InterruptedException，则线程并没有中断，通过thread.isInterrupted()返回中断位为false；
     *  3、在方法出现InterruptedException时，如果能处理中断异常则处理，不能处理则上抛或再次执行thread.interrupt()方法，中断该线程；
     */
    public static void testInterrupt2() throws InterruptedException {
        Student student = new Student();
        Thread thread = new Thread(student, "张飞");
        thread.start();

        Thread thread2 = new Thread(student, "关羽");
        thread2.start();

        //5s后，中断关羽同学学习，给他打个电话
        TimeUnit.SECONDS.sleep(1);
        thread2.interrupt();
    }
}


class Student implements Runnable {

    //注意：这里使用volatile修饰中断标志位，保证该字段的内存可见性。
    private volatile boolean interrupted = false;


    public void study() {
        System.out.println("学生" + Thread.currentThread().getName() + "学习中~~");
    }

    @Override
    public void run() {
        Thread current = Thread.currentThread();
        //当自定义中断位为true或者当前线程被中断时，退出循环
        while (!interrupted && !current.isInterrupted()) {
            //没被中断时，学生一直在学习
            study();

            //睡眠1s
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                //被中断的线程，出现异常，则会清除中断标志位（thread.isInterrupted()方法返回false，而不是true），针对这种情况，
                //可以将interruptedException异常继续往上抛出或者是再次调用thread.interrupt()方法，更新当前线程的中断标志位。
                System.out.println(current.getName() + "-isInterrupted=" + current.isInterrupted());
                current.interrupt();
            }
        }

        System.out.println(Thread.currentThread().getName() + "电话来了，被中断了，去接个电话~~");
    }

    //提供方法，将自定义中断位状态更新
    public void interrupt() {
        interrupted = true;
    }
}
